package fr.ece.ing4.si.gui;

import fr.ece.ing4.si.core.*;
import fr.ece.ing4.si.multithread.MultiThreadMonteCarlo;
import fr.ece.ing4.si.singlethread.*;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.FlowLayout;
import java.io.IOException;

import java.util.ArrayList;
import java.util.concurrent.ExecutionException;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextField;
import javax.swing.JComboBox;
import javax.swing.JPanel;
import javax.swing.JProgressBar;

public class MonteCarloGUI extends JFrame implements ActionListener {

    ArrayList<JPanel> panels;
    JLabel argSetsLabel;
    ArrayList<JButton> argSetButtons;
    JLabel optionFlagLabel;
    JComboBox optionFlagComboBox;
    ArrayList<JLabel> argLabels;
    ArrayList<JTextField> argTextFields;
    JProgressBar progressBar;
    JButton singleThreadComputeButton;
    JButton multiThreadComputeButton;
    
    MonteCarloArgs MCArgs = new MonteCarloArgs();
    SingleThreadMonteCarlo sequentialMC = new SingleThreadMonteCarlo();
    MultiThreadMonteCarlo multiThreadedMC = new MultiThreadMonteCarlo();
    
    @Override
    protected void frameInit() {
        super.frameInit();
        getContentPane().setLayout(new FlowLayout());
        
        panels = new ArrayList();
        
        for (int i = 0; i<4; i++) {
            panels.add(new JPanel());
            panels.get(i).setLayout(new FlowLayout());
            getContentPane().add(panels.get(i));
        }
        
        argSetsLabel = new JLabel("Choose a preloaded model: ");
        panels.get(0).add(argSetsLabel);
        
        argSetButtons = new ArrayList();
        for (int i = 0; i<5; i++) {
            argSetButtons.add(new JButton(String.valueOf(i+1)));
            argSetButtons.get(i).addActionListener(this);
            panels.get(0).add(argSetButtons.get(i));
        }
        
        optionFlagLabel = new JLabel("Option Flag");
        panels.get(1).add(optionFlagLabel);
        optionFlagComboBox = new JComboBox(EOptionFlag.values());
        panels.get(1).add(optionFlagComboBox);
        
        argLabels = new ArrayList();
        argTextFields = new ArrayList();
        String[] argName = { "S", "X", "T", "r", "b", "v", "nSteps", "nSimulations" };
        for (int i = 0; i<8; i++) {
            argLabels.add(new JLabel(argName[i]));
            argTextFields.add(new JTextField(5));
            panels.get(1).add(argLabels.get(i));
            panels.get(1).add(argTextFields.get(i));
        }
        
        singleThreadComputeButton = new JButton("SingleThread Compute");
        multiThreadComputeButton = new JButton("Multithread Compute");
        singleThreadComputeButton.addActionListener(this);
        multiThreadComputeButton.addActionListener(this);
        panels.get(2).add(singleThreadComputeButton);
        panels.get(2).add(multiThreadComputeButton);
        
        progressBar = new JProgressBar(0, 100);
        progressBar.setValue(47);
        panels.get(3).add(progressBar);
        
        this.setSize(870, 160);
        this.setVisible(true);
        this.setTitle("Monte Carlo API");
        this.setResizable(false);
        this.setLocation(100, 100);
        this.setDefaultCloseOperation(EXIT_ON_CLOSE);
    }

    public void actionPerformed(ActionEvent e) {
        Object o = e.getSource();
        
        for (int i=0 ; i<argSetButtons.size() ; i++) {
            if (o == argSetButtons.get(i)) {
                try {
                    MCArgs.setArgsFromModel(i+1);
                    refreshOptionFlagComboBox(MCArgs);
                    refreshArgTextFields(MCArgs);
                } catch (IOException ex) {
                    System.out.println (ex.toString());
                }
            }
        }
        
        if (o == singleThreadComputeButton) {
            MCArgs.S = Double.parseDouble(argTextFields.get(0).getText());
            MCArgs.X = Double.parseDouble(argTextFields.get(1).getText());
            MCArgs.T = Double.parseDouble(argTextFields.get(2).getText());
            MCArgs.r = Double.parseDouble(argTextFields.get(3).getText());
            MCArgs.b = Double.parseDouble(argTextFields.get(4).getText());
            MCArgs.v = Double.parseDouble(argTextFields.get(5).getText());
            MCArgs.nSteps = Integer.parseInt(argTextFields.get(6).getText());
            MCArgs.nSimulations = Integer.parseInt(argTextFields.get(7).getText());
            try {
				sequentialMC.timeAndCompute(MCArgs);
			} catch (InterruptedException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			} catch (ExecutionException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
        }
        
        else if (o == multiThreadComputeButton) {
            MCArgs.S = Double.parseDouble(argTextFields.get(0).getText());
            MCArgs.X = Double.parseDouble(argTextFields.get(1).getText());
            MCArgs.T = Double.parseDouble(argTextFields.get(2).getText());
            MCArgs.r = Double.parseDouble(argTextFields.get(3).getText());
            MCArgs.b = Double.parseDouble(argTextFields.get(4).getText());
            MCArgs.v = Double.parseDouble(argTextFields.get(5).getText());
            MCArgs.nSteps = Integer.parseInt(argTextFields.get(6).getText());
            MCArgs.nSimulations = Integer.parseInt(argTextFields.get(7).getText());
            try {
				multiThreadedMC.timeAndCompute(MCArgs);
			} catch (InterruptedException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			} catch (ExecutionException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
        }
    }
    
    private void refreshArgTextFields(MonteCarloArgs MCArgs) {
        argTextFields.get(0).setText(String.format("%.2f", MCArgs.S).replace(',', '.'));
        argTextFields.get(1).setText(String.format("%.2f", MCArgs.X).replace(',', '.'));
        argTextFields.get(2).setText(String.format("%.2f", MCArgs.T).replace(',', '.'));
        argTextFields.get(3).setText(String.format("%.2f", MCArgs.r).replace(',', '.'));
        argTextFields.get(4).setText(String.format("%.2f", MCArgs.b).replace(',', '.'));
        argTextFields.get(5).setText(String.format("%.2f", MCArgs.v).replace(',', '.'));
        argTextFields.get(6).setText(String.format("%d", MCArgs.nSteps).replace(',', '.'));
        argTextFields.get(7).setText(String.format("%d", MCArgs.nSimulations).replace(',', '.'));
    }
    
    private void refreshOptionFlagComboBox(MonteCarloArgs MCArgs) {
        optionFlagComboBox.setSelectedItem(MCArgs.flag);
    }
}
